Baffled by Runtime Exception Error

Hi,

I've been trying to clean up some memory leaks in an old DXL script, and for one particular function I was attempting to delete a local skip list before the end of the function, but I'm receiving the following runtime error when processing the last find() line before the delete() and return:

An unexpected error has occurred: general_library.dll caused an EXCEPTION_ACCESS_VIOLATION in module general_library.dll at 0023:10008389

 

The original function before I made additions was as follows, and doesn't produce the runtime error. In case it matters, skAttrValsAtSave is a global skip list containing skip lists of attribute values

string attrValueAtSave(Object o, string attr, string unsavedVal)
{
        Skip sk = null
        string savedVal
        int absNum = o."Absolute Number"
        if(!unsaved(o)) return unsavedVal
        if(!find(skAttrValsAtSave, absNum, sk)) return unsavedVal
        if(!find(sk, attr, savedVal)) return unsavedVal
        
        return savedVal
}

The new modified function which produces the runtime error is as follows:

string attrValueAtSave(Object o, string attr, string unsavedVal)
{
        Skip sk = null
        string savedVal
        int absNum = o."Absolute Number"
        if(!unsaved(o)) return unsavedVal
        if(!find(skAttrValsAtSave, absNum, sk)) return unsavedVal
        if(!find(sk, attr, savedVal))          <------- ERRORS HERE
        {
                if (!null sk)
                        delete sk
                return unsavedVal
        }
        
        if (!null sk)
                delete sk
        
        return savedVal
}

I understand that context may be necessary so I apologize if it is impossible to even begin discerning the cause of the error without the context of the rest of the script, but if anyone has some thoughts right off the top of their head what could possibly be causing this, any ideas would be greatly appreciated.


Dan Chen - Tue Oct 29 11:36:19 EDT 2019

Re: Baffled by Runtime Exception Error
Mike.Scharnow - Tue Oct 29 12:03:55 EDT 2019

It seems that sk has already been deleted, the error possibly occurs when you call the function for the second time.

After the first call, skAttrValsatSave, absNum points to invalid content.

And: in line 10 you ask whether sk is null, but in line 8 you already use sk - this cannot work.

Perhaps something like this may work

string attrValueAtSave(Object o, string attr, string unsavedVal)
{
        Skip sk = null
        string savedVal
        int absNum = o."Absolute Number"
        if(!unsaved(o)) return unsavedVal
        if(!find(skAttrValsAtSave, absNum, sk)) return unsavedVal
                
        // should not occur, but better safe than sorry
        if (null sk) return unsavedVal
                
                
        string retVal = unsavedVal
        if (find (sk, attr, savedVal)) {
                retVal = savedVal
        }
        
        // sk has been used, it is not needed any more. 
        // Free the memory and remove it from the containing list
        delete sk
        delete (skAttrValsAtSave, absNum)
        
        return retVal
}

 

 

Re: Baffled by Runtime Exception Error
Dan Chen - Tue Oct 29 12:28:26 EDT 2019

Mike.Scharnow - Tue Oct 29 12:03:55 EDT 2019

It seems that sk has already been deleted, the error possibly occurs when you call the function for the second time.

After the first call, skAttrValsatSave, absNum points to invalid content.

And: in line 10 you ask whether sk is null, but in line 8 you already use sk - this cannot work.

Perhaps something like this may work

string attrValueAtSave(Object o, string attr, string unsavedVal)
{
        Skip sk = null
        string savedVal
        int absNum = o."Absolute Number"
        if(!unsaved(o)) return unsavedVal
        if(!find(skAttrValsAtSave, absNum, sk)) return unsavedVal
                
        // should not occur, but better safe than sorry
        if (null sk) return unsavedVal
                
                
        string retVal = unsavedVal
        if (find (sk, attr, savedVal)) {
                retVal = savedVal
        }
        
        // sk has been used, it is not needed any more. 
        // Free the memory and remove it from the containing list
        delete sk
        delete (skAttrValsAtSave, absNum)
        
        return retVal
}

 

 

Hey Mike,

 

Thank you so much for your help! It has caused me to wonder if I understand how skip lists operate. You indicated in your reply, "After the first call, skAttrValsatSave, absNum points to invalid content."

So does that mean delete sk actually also deletes the value stored in memory pointed to by the skip list skAttrValsAtSave with key absNum? I guess I was under the impression skip lists acted like arrays and find(skAttrValsAtSave, absNum, sk) created a copy of the skip list and it's referenced values and stored it in sk, and that even after I delete sk, find(skAttrValsAtSave, absNum, sk) could again retrieve a copy and store it in sk?

 

And then the followup question to that would be, since I still need to retain the values in skAttrValsAtSave, is there a way to clean up sk without modifying the values of skAttrValsAtSave, or is a "cleanup" even necessary?

Re: Baffled by Runtime Exception Error
Mike.Scharnow - Tue Oct 29 12:54:59 EDT 2019

Hello Dan,

Skip Lists work like Hashes in Perl or HashMap in Java, i.e. you have a collection of "things" (values) that can be accessed by a key. The "thing" can be anything, a string, an integer, an array, an Array or even another skip.

It is totally up to you what you use as key or value, as long as a) you are consistent in the data types throughout the whole program and b) if your skip list uses strings as keys, you need to create it using createString() instead of create().

The perm 

bool find (Skip s, type1 key, type2 &data)

will a) return true or false, depending on whether the skip list contains an entry with key "key" and b) if found, will set the variable "data" to the value of the found entry. For simple types like integer, this will be the value itself, for objects / data structures, this will be a "pointer/reference".

From your comment and your script, I understand that you have one skip list called skAttrValsAtSave with key = integer, corresponding to the absolute number of an object and value = skip list with key = string, corresponding to the name of an attribute and value = string, corresponding to the value of the attribute of the object at some specific time.

So, back to your script: in line 7 the local variable sk is set so that it *point*s to the skip list contained in the value of skAttrValsAtSave, absNum.

If the sole purpose of this script is to *get* the value stored at skAttrValsAtSave→absNum→attr, then you do not need to cleanup any data after reading it.

Only when you don't need the information any more and want to free it from memory for the rest of your script's run time, you may need to a) get a pointer to the (inner) Skip list, b) free the memory of the Skip (using delete sk) and c) remove the reference from the containing (outer) Skip

Re: Baffled by Runtime Exception Error
Dan Chen - Tue Oct 29 13:01:19 EDT 2019

Appreciate the thorough explanation Mike! Yes, you accurately pinpointed the purpose of the function, that is to merely *get* the value stored without a need to delete the stored value. I will go ahead and remove the delete() as you have recommended and not worry about cleanup. Thank you!